package com.sys.guacamole;

import org.apache.guacamole.protocol.GuacamoleConfiguration;

/**
 * 添加RDP连接
 * 如果您使用的是Guacamole内置的默认身份验证，并且希望向特定用户授予对RDP连接的访问​​权限，则需要在中找到该<authorize>用户的 部分 user-mapping.xml，并在其中添加以下部分：
 * <p>
 * <connection name =“ Unique Name”>
 * <protocol> rdp </ protocol>
 * <param name =“主机名”> localhost</ param>
 * <param name =“ servicePort”> 3389</ param>
 * </ connection>
 * 如果完全按照上述方法添加，则名为“ Unique Name” 的新连接将可供与<authorize>包含它的部分关联的用户使用 。连接将使用RDP连接到localhost端口 3389。自然，您将要更改其中一些或所有值。
 * <p>
 * 如果要自动登录而不是在连接时收到登录提示，则可以指定用户名和密码以及其他 <param>标签。其他选项可用于控制颜色深度，屏幕尺寸等。
 * <p>
 * 其他身份验证方法将提供描述如何配置新连接的文档。如果使用的身份验证方法完全实现了Guacamole身份验证API的功能，则您将能够使用Guacamole内置的管理界面轻松直观地添加新的RDP连接。您将不需要编辑配置文件。
 * <p>
 * <p>
 * RDP协议比VNC更为复杂，并且是Guacamole官方支持的第二个协议。由于使用了缓存，因此RDP往往比VNC更快，Guacamole确实利用了缓存。
 * <p>
 * libguac-client-rdp 库提供了对Guacamole的RDP支持，如果在构建过程中存在必需的依赖项，它将作为guacamole-server的一部分安装。
 */
public class GuacamoleRDP extends Guacamole {

    public GuacamoleRDP() {
        super();
    }

    /**
     * @param hostname 主机名称
     * @param port     主机端口
     */
    public GuacamoleRDP(String hostname, Integer port) {
        super(hostname, port);
    }

    /**
     * 网络参数
     * <p>
     * RDP连接需要定义目标计算机的主机名或IP地址。RDP端口定义为3389，在大多数情况下将为该值。如果不使用端口3389，则仅需要指定RDP端口。
     * <p>
     * SSH连接需要定义目标计算机的主机名或IP地址。SSH被标准化为使用端口22，在大多数情况下，这将是正确的值。如果不使用标准端口，则只需指定SSH端口。
     * <p>
     * Telnet连接需要定义目标计算机的主机名或IP地址。Telnet被标准化为使用端口23，并且在大多数情况下这将是正确的值。如果不使用标准端口，则只需指定telnet端口。
     *
     * @param hostname 子服务端ip
     * @param port     子服务端端口
     */
    public void setGuacamoleConfiguration(String hostname, Integer port) {
        super.guacamoleConfiguration = new GuacamoleConfiguration();
        super.guacamoleConfiguration.setProtocol("rdp");
        super.guacamoleConfiguration.setParameter("hostname", hostname);
        super.guacamoleConfiguration.setParameter("port", String.valueOf(port));
    }

    /**
     * 身份验证和安全性,可选方法
     * <p>
     * RDP通过使用用户名，密码和可选域来提供身份验证。
     * 如果省略了用户名，密码和域参数，大多数RDP服务器将提供图形登录。
     * 一个明显的例外是网络级身份验证或NLA，它在桌面会话之外并因此在没有图形界面的情况下执行所有身份验证。
     * 如果您的服务器需要NLA，则需要手动选择此方式作为安全模式，并且必须提供用户名和密码。
     * <p>
     * 所有RDP连接都是加密的。更高级别的加密以TLS（另一种可能的安全模式）的形式可用。
     *
     * @param username    用于验证的用户名（如果有）。此参数是可选的。
     * @param password    尝试身份验证时使用的密码（如果有）。此参数是可选的。
     * @param domain      尝试身份验证时使用的域（如果有）。此参数是可选的。
     * @param security    用于RDP连接的安全模式。此模式指示如何加密数据以及将执行哪种身份验证（如果有）。默认情况下，要求使用标准RDP加密，因为它受到最广泛的支持。 可能的值为：
     *                    <p>
     *                    rdp
     *                    标准RDP加密。这是默认设置，所有RDP服务器都应支持。
     *                    <p>
     *                    nla
     *                    网络级身份验证。此模式需要用户名和密码，并在远程桌面会话实际开始之前执行身份验证步骤。如果未提供用户名和密码，则无法建立连接。
     *                    <p>
     *                    tls
     *                    TLS加密。TLS（传输层安全性）是SSL的后继产品。
     *                    <p>
     *                    any
     *                    允许服务器选择安全性类型。
     * @param ignoreCert  如果设置为“ true”，则服务器返回的证书将被忽略，即使该证书无法通过验证也是如此。
     *                    如果您普遍信任服务器以及与服务器的连接，并且知道服务器的证书无法验证（例如，如果它是自签名的），则这很有用。
     * @param disableAuth 如果设置为“ true”，则将禁用身份验证。请注意，这是指在连接时进行的身份验证。
     *                    服务器通过远程桌面会话强制执行的任何身份验证（例如登录对话框）仍将进行。默认情况下，身份验证处于启用状态，仅在服务器请求时才使用。
     *                    如果使用NLA，则必须通过定义启用身份验证。
     */
    public void authenticationAndSecurity(String username, String password, String domain,
                                          Security security, boolean ignoreCert, boolean disableAuth) {
        if (username != null) {
            super.getGuacamoleConfiguration().setParameter("username", username);
        }
        if (password != null) {
            super.getGuacamoleConfiguration().setParameter("password", password);
        }
        if (domain != null) {
            super.getGuacamoleConfiguration().setParameter("domain", domain);
        }
        if (security != null) {
            super.getGuacamoleConfiguration().setParameter("security", security.getValue());
        }
        super.getGuacamoleConfiguration().setParameter("ignore-cert", String.valueOf(ignoreCert));
        super.getGuacamoleConfiguration().setParameter("disable-auth", String.valueOf(disableAuth));
    }

    /**
     * 会话设置
     * <p>
     * RDP会话通常会涉及普通用户的完整桌面环境。
     * 或者，您可以手动指定要使用的程序而不是RDP服务器的默认外壳程序，或连接到管理控制台。
     * <p>
     * 尽管鳄梨酱不依赖于键盘布局，但RDP并非如此。
     * 这是因为，鳄梨表示根据他们什么键做 （“按回车键”），而RDP使用基于密钥的位置标识符（“按第二排最右边的键”）。
     * 要在鳄梨酱键事件和RDP键事件之间进行转换，鳄梨酱必须提前知道RDP服务器的键盘布局。
     * <p>
     * 默认情况下，将使用美国英语qwerty键盘。如果这与RDP服务器的键盘布局不匹配，则将无法正确转换键，因此您需要在连接设置中明确选择其他布局。
     * 如果不支持您的键盘布局，请通过在JIRA中打开问题来通知鳄梨酱团队。
     *
     * @param clientName     连接到RDP服务器时，Guacamole通常将提供其自己的主机名作为客户端名称。如果指定了此参数，则鳄梨调味酱会代替它的值。
     *                       在Windows RDP服务器上，此值在会话中作为CLIENTNAME环境变量公开。
     *                       <p>
     * @param console        如果设置为“ true”，则将连接到RDP服务器的控制台（admin）会话。
     *                       <p>
     * @param initialProgram 连接后立即运行的程序的完整路径。此参数是可选的。
     *                       <p>
     * @param serverLayout   服务器端键盘布局。这是RDP服务器的布局，与客户端上使用的键盘布局无关。鳄梨酱客户端独立于键盘布局。
     *                       但是，RDP协议 并不独立于键盘布局，Guacamole需要知道服务器的键盘布局，以便在用户键入内容时发送正确的键。
     */
    public void sessionSettings(String clientName, boolean console, String initialProgram, ServerLayout serverLayout) {
        super.getGuacamoleConfiguration().setParameter("client-name", clientName);
        super.getGuacamoleConfiguration().setParameter("console", String.valueOf(console));
        if (initialProgram != null) {
            super.getGuacamoleConfiguration().setParameter("initial-program", initialProgram);
        }
        if (serverLayout != null) {
            super.getGuacamoleConfiguration().setParameter("server-layout", serverLayout.getValue());
        }
    }

    /**
     * 显示设置
     * 鳄梨酱会根据浏览器窗口的大小和设备的DPI为RDP连接自动选择合适的显示大小。
     * 可以通过指定显式的宽度或高度值来强制显示大小。
     * <p>
     * 为了减少带宽使用，您还可以要求服务器减小其颜色深度。
     * 鳄梨调味酱会自动检测256色图像，但是通过将颜色深度强制为8位，可以绝对保证通过连接发送的所有图形。
     * 否则，颜色深度由RDP服务器决定。
     *
     * @param colorDepth   请求的颜色深度，以每像素为单位。此参数是可选的。如果指定，则该值必须为8、16或24。
     *                     无论在此处选择什么值，如果特定更新使用的颜色少于256种颜色，则鳄梨鳄梨酱将始终将该更新作为256色PNG发送。
     * @param width        要请求的显示宽度，以像素为单位。此参数是可选的。如果未指定此值，则将使用连接客户端显示的宽度。
     * @param height       要请求的显示高度，以像素为单位。此参数是可选的。如果未指定此值，则将使用连接客户端显示的高度。
     * @param dpi          客户端显示所需的有效分辨率，以DPI为单位。此参数是可选的。如果未指定此值，则将一起使用客户端显示的分辨率和大小来确定RDP会话的合适分辨率。
     * @param resizeMethod 客户端显示的宽度或高度更改时用于更新RDP服务器的方法。此参数是可选的。如果未指定此值，则客户端显示更改大小时将不执行任何操作。
     *                     <p>
     *                     通常，RDP会话的显示大小是恒定的，只能在最初连接时更改。从RDP 8.1开始，“显示更新”通道可用于请求服务器更改显示大小。对于较旧的RDP服务器，唯一的选择是断开连接并使用新的大小重新连接。
     *                     <p>
     *                     可能的值为：
     *                     <p>
     *                     display-update
     *                     当客户端显示大小更改时，使用随RDP 8.1一起添加的“显示更新”通道向服务器发出信号。
     *                     <p>
     *                     reconnect
     *                     客户端显示大小更改后，将自动断开RDP会话的连接，并以新的大小重新连接。
     */
    public void displaySettings(String colorDepth, Integer width, Integer height, Integer dpi, ResizeMethod resizeMethod) {
        if (colorDepth != null) {
            super.getGuacamoleConfiguration().setParameter("color-depth", colorDepth);
        }
        if (width != null) {
            super.getGuacamoleConfiguration().setParameter("width", String.valueOf(width));
        }
        if (height != null) {
            super.getGuacamoleConfiguration().setParameter("height", String.valueOf(height));
        }
        if (dpi != null) {
            super.getGuacamoleConfiguration().setParameter("dpi", String.valueOf(dpi));
        }
        if (resizeMethod != null) {
            super.getGuacamoleConfiguration().setParameter("resize-method", resizeMethod.getValue());
        }
    }

    /**
     * 控制台会话
     *
     * @param is           如果设置为“ true”，则将连接到RDP服务器的控制台（admin）会话。
     *                     <p>
     * @param consoleAudio 如果设置为“ true”，则将在RDP服务器的控制台（admin）会话中显式启用音频。
     *                     仅当console参数也设置为“ true”时，将此选项设置为“ true”才有意义 。
     */
    public void console(boolean is, boolean consoleAudio) {
        super.getGuacamoleConfiguration().setParameter("console", String.valueOf(is));
        super.getGuacamoleConfiguration().setParameter("console-audio", String.valueOf(consoleAudio));
    }

    /**
     * 开启关闭音频
     * 默认情况下，客户端和libguac-client-rdp中都启用了音频。如果您担心带宽使用或声音引起问题，可以通过将此参数设置为“ true”来显式禁用声音。
     */
    public void disableAudio(boolean is) {
        super.getGuacamoleConfiguration().setParameter("disable-audio", String.valueOf(is));
    }

    /**
     * 开启关闭麦克风
     * 如果设置为“ true”，则将利用RDP的标准“ AUDIO-INPUT”通道来启用音频输入支持（麦克风）。默认情况下，禁用RDP中的音频输入支持。
     */
    public void enableAudioInput(boolean is) {
        super.getGuacamoleConfiguration().setParameter("enable-audio-input", String.valueOf(is));
    }

    /**
     * 开启关闭打印机
     *
     * @param enablePrinting 默认情况下，打印是禁用的，但是启用打印后，RDP用户可以打印到虚拟打印机，该虚拟打印机将包含已打印文档的PDF发送到Guacamole客户端。通过将此参数设置为“ true”来启用打印。
     *                       打印支持要求 安装GhostScript。如果 在打印时 guacd无法找到 gs可执行文件，则打印尝试将失败。
     *                       <p>
     * @param printerName    传递到RDP会话的重定向打印机设备的名称。这是用户将在例如“设备和打印机”控制面板中看到的名称。
     *                       如果未启用打印机重定向，则此选项无效。
     */
    public void printer(boolean enablePrinting, String printerName) {
        super.getGuacamoleConfiguration().setParameter("enable-printing", String.valueOf(enablePrinting));
        if (printerName != null && !printerName.equals("")) {
            super.getGuacamoleConfiguration().setParameter("printer-name", printerName);
        }
    }

    /**
     * 设置文件传输
     *
     * @param enableDrive     默认情况下，文件传输是禁用的，但是启用文件传输后，RDP用户可以与Guacamole服务器上持久存在的虚拟驱动器进行文件传输。通过将此参数设置为“ true”来启用文件传输支持。
     *                        文件将存储在“ drive-path”参数指定的目录中，如果启用了文件传输，则需要此文件。
     *                        <p>
     * @param driveName       传递到RDP会话时使用的文件系统的名称。这是用户将在其“计算机/我的电脑”区域中看到的名称以及客户端名称（例如“ Guacamole RDP上的Guacamole”），也是访问特殊\\tsclient 网络位置时共享的名称。
     *                        如果未启用文件传输，则忽略此参数
     *                        <p>
     * @param drivePath       Guacamole服务器上的目录，应在其中存储传输的文件。此目录必须可由guacd访问，并且运行guacd的用户可以读写。此参数不引用RDP服务器上的目录。
     *                        如果未启用文件传输，则忽略此参数。
     *                        <p>
     * @param createDrivePath 如果设置为“ true”，并且启用了文件传输，则该drive-path 参数指定的目录（如果尚不存在）将自动创建。仅将创建路径中的最终目录-如果路径中较早的其他目录不存在，则自动创建将失败，并且将记录错误。
     *                        默认情况下，drive-path不会自动创建该参数指定的目录 ，并且将文件传输到不存在的目录的尝试将记录为错误。
     *                        如果未启用文件传输，则忽略此参数。
     */
    public void driveFile(boolean enableDrive, String driveName, String drivePath, boolean createDrivePath) {
        super.getGuacamoleConfiguration().setParameter("enable-drive", String.valueOf(enableDrive));
        if (driveName != null) {
            super.getGuacamoleConfiguration().setParameter("enable-name", driveName);
        }
        if (drivePath != null) {
            super.getGuacamoleConfiguration().setParameter("enable-path", drivePath);
        }
        super.getGuacamoleConfiguration().setParameter("create-drive-path", String.valueOf(createDrivePath));
    }

    /**
     * 如果设置为“ true”，则将在RDP服务器的控制台（admin）会话中显式启用音频。仅当consoleconsole参数也设置为“ true”时，将此选项设置为“ true”才有意义 。
     */
    public void consoleAudio(boolean is) {
        super.getGuacamoleConfiguration().setParameter("console-audio", String.valueOf(is));
    }

    /**
     * 远程桌面网关
     * <p>
     * Microsoft的远程桌面服务器提供了额外的网关服务，该服务允许将外部连接转发到内部RDP服务器，否则将无法访问这些服务器。
     * 如果要使用Guacamole通过此类网关进行连接，则需要提供其他参数来描述与该网关的连接以及所有必需的凭据。
     * <p>
     * 仅当鳄梨酱是针对FreeRDP 1.1或更高版本构建的时，此功能才可用。较旧的FreeRDP版本不支持RDP网关。
     *
     * @param gatewayHostname gateway-serviceHostname
     *                        远程桌面网关的主机名，应用作远程桌面连接的中介。如果省略，将不使用网关。
     * @param gatewayPort     gateway-servicePort
     *                        远程桌面网关的端口，应用作远程桌面连接的中介。默认情况下，这将是“ 443”。
     *                        如果使用FreeRDP 1.2之前的版本，则此设置无效。较旧的FreeRDP版本使用“ 443”的硬编码值。
     * @param gatewayUsername gateway-username
     *                        如果正在使用网关，则使用远程桌面网关进行身份验证的用户的用户名。这不一定与实际使用远程桌面连接的用户相同。
     * @param gatewayPassword gateway-password
     *                        与远程桌面网关进行身份验证时提供的密码（如果正在使用网关）。
     * @param gatewayDomain   gateway-domain
     *                        如果正在使用网关，则使用远程桌面网关进行身份验证的用户域。该域不一定与实际使用远程桌面连接的用户所在的域相同。
     */
    public void remoteDesktopGateway(String gatewayHostname, Integer gatewayPort, String gatewayUsername,
                                     String gatewayPassword, String gatewayDomain) {
        super.getGuacamoleConfiguration().setParameter("gateway-serviceHostname", gatewayHostname);
        if (gatewayPort == null) {
            super.getGuacamoleConfiguration().setParameter("gateway-servicePort", "443");
        } else {
            super.getGuacamoleConfiguration().setParameter("gateway-servicePort", String.valueOf(gatewayPort));
        }

        super.getGuacamoleConfiguration().setParameter("gateway-username", gatewayUsername);
        super.getGuacamoleConfiguration().setParameter("gateway-password", gatewayPassword);
        super.getGuacamoleConfiguration().setParameter("gateway-domain", gatewayDomain);
    }

    /**
     * 负载平衡和RDP连接代理
     * <p>
     * 如果远程桌面服务器位于负载平衡器（有时称为“连接代理”或“ TS会话代理”）后面，则该平衡器在连接过程中可能需要其他信息来确定应如何路由传入的连接。
     * RDP并未规定此信息的格式；它特定于使用中的平衡器。
     * <p>
     * 如果您使用的是负载平衡器，并且不确定是否需要此类信息，则需要查看平衡器的文档。
     * 如果您的平衡器.rdp 为方便起见而提供文件，请在这些文件的内容中查找一个名为“ loadbalanceinfo”的字符串字段，因为该字段将在其中指定所需的信息/ cookie。
     * <p>
     * 仅当鳄梨酱是针对FreeRDP 1.1或更高版本构建的时，此功能才可用。
     * 较旧的FreeRDP版本不支持负载平衡器，该负载平衡器在连接过程中需要其他信息。
     */
    public void loadBalancingAndRDPConnectionBrokers(String loadBalanceInfo) {
        if (loadBalanceInfo != null && !loadBalanceInfo.equals("")) {
            super.getGuacamoleConfiguration().setParameter("load-balance-info", loadBalanceInfo);
        }
    }

    /**
     * 文件传输Sftp
     * <p>
     * 鳄梨酱可以通过SFTP提供文件传输，即使通过RDP（而不是SSH）访问远程桌面也是如此。
     * 如果在Guacamole RDP连接上启用了SFTP，则用户将能够按照第15章“ 使用Guacamole”中的说明上载和下载文件。
     * <p>
     * 这种支持独立于通过RDP自己的“驱动器重定向”（RDPDR）实现的文件传输，并且对于不支持RDPDR的RDP服务器特别有用。
     * <p>
     *
     * @param enableSftp              是否应启用文件传输。如果设置为“ true”，则将允许用户使用SFTP从指定的服务器上载或下载文件。如果省略，将禁用SFTP。
     *                                <p>
     * @param sftpHostname            托管SFTP的服务器的主机名或IP地址。此参数是可选的。如果省略，将使用通过hostname参数指定的RDP服务器的主机名 。
     *                                <p>
     * @param sftpPort                提供SFTP的SSH服务器正在侦听的端口，通常为22。此参数是可选的。如果省略，将使用标准端口22。
     *                                <p>
     * @param sftpHostKey             SFTP服务器的已知主机条目。该参数是可选的，如果未提供，则不会完成SFTP主机身份的验证。如果提供了参数，则将根据数据检查服务器的身份。
     *                                此参数的格式是OpenSSH known_hosts文件中单个条目的格式。
     *                                有关更多信息，请参见“ SSH主机验证”部分。
     *                                <p>
     * @param sftpUsername            连接到用于SFTP的指定SSH服务器时进行身份验证的用户名。如果为RDP连接指定了用户名，则此参数是可选的。如果省略，username 将使用为参数提供的值。
     *                                <p>
     * @param sftpPassword            与指定的SSH服务器进行SFTP身份验证时使用的密码。
     *                                <p>
     * @param sftpPrivateKey          用于公钥认证的私钥的全部内容。如果未指定此参数，将不使用公共密钥身份验证。私钥必须采用OpenSSH格式，就像由OpenSSH ssh-keygen实用程序生成的那样。
     *                                <p>
     * @param sftpPassphrase          用于解密私钥以用于公钥身份验证的密码短语。如果私钥不需要密码，则不需要此参数。
     *                                <p>
     * @param sftpDirectory           如果只是将文件拖放到文件上载的目录，则否则缺少特定的上载位置。此参数是可选的。如果省略，将使用提供SFTP的SSH服务器的默认上传位置。
     *                                <p>
     * @param sftpRootDirectory       通过Guacamole的文件浏览器向连接的用户公开的目录 。如果省略，则默认使用根目录。
     *                                <p>
     * @param sftpServerAliveInterval SFTP连接发送keepalive报文到SSH服务器的时间间隔（秒）。此参数是可选的。如果省略，将使用默认值0，从而禁用发送keepalive数据包的功能。最小值是2。
     */
    public void rdpSftp(boolean enableSftp, String sftpHostname, Integer sftpPort, String sftpHostKey, String sftpUsername, String sftpPassword,
                        String sftpPrivateKey, String sftpPassphrase, String sftpDirectory, String sftpRootDirectory, Integer sftpServerAliveInterval) {
        super.getGuacamoleConfiguration().setParameter("static-channels", String.valueOf(enableSftp));
        if (sftpHostname != null && !sftpHostname.equals("")) {
            super.getGuacamoleConfiguration().setParameter("sftp-serviceHostname", sftpHostname);
        }
        if (sftpPort != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-servicePort", String.valueOf(sftpPort));
        }
        if (sftpHostKey != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-host-createIdKey", sftpHostKey);
        }
        if (sftpUsername != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-username", sftpUsername);
        }
        super.getGuacamoleConfiguration().setParameter("sftp-password", sftpPassword);
        if (sftpPrivateKey != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-private-createIdKey", sftpPrivateKey);
        }
        if (sftpPassphrase != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-passphrase", sftpPassphrase);
        }
        if (sftpDirectory != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-directory", sftpDirectory);
        }
        if (sftpRootDirectory != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-root-directory", sftpRootDirectory);
        }
        if (sftpServerAliveInterval != null) {
            super.getGuacamoleConfiguration().setParameter("sftp-server-alive-interval", String.valueOf(sftpServerAliveInterval));
        }
    }

    /**
     * 性能标志
     * <p>
     * RDP提供了几个标志，这些标志控制着功能的可用性，这些功能出于美观的目的而降低了性能并增加了带宽，例如墙纸，窗口主题，菜单效果和平滑字体。
     * 默认情况下，在Guacamole中，所有这些功能都是禁用的，这样可以最大程度地减少带宽使用，但是如果需要，您可以在每个连接的基础上手动重新启用它们。
     * <p>
     *
     * @param enableWallpaper          如果设置为“ true”，则启用渲染桌面墙纸。默认情况下，墙纸将被禁用，从而无需花费不必要的带宽来重新绘制桌面。
     *                                 <p>
     * @param enableTheming            如果设置为“ true”，则启用窗口和控件的主题设置。默认情况下，RDP会话中的主题设置为禁用。
     *                                 <p>
     * @param enableFontSmoothing      如果设置为“ true”，则文本将以平滑的边缘呈现。默认情况下，RDP上的文本呈现为粗糙的边缘，因为这会减少文本使用的颜色数量，从而减少连接所需的带宽。
     *                                 <p>
     * @param enableFullWindowDrag     如果设置为“ true”，则窗口的内容将随着窗口的移动而显示。默认情况下，RDP服务器将仅在拖动窗口时绘制窗口边框。
     *                                 <p>
     * @param enableDesktopComposition 如果设置为“ true”，则将允许图形效果，例如透明的窗口和阴影。默认情况下，此类效果（如果可用）是禁用的。
     *                                 <p>
     * @param enableMenuAnimations     如果设置为“ true”，则允许菜单打开和关闭动画。默认情况下，菜单动画是禁用的。
     *                                 <p>
     * @param disableBitmapCaching     在某些情况下，尤其是对于具有已知错误的RDP服务器实现，有必要禁用RDP的内置位图缓存功能。此参数允许在鳄梨酱会话中对其进行控制。
     *                                 如果设置为“ true”，将不使用RDP位图缓存。
     *                                 <p>
     * @param disableOffscreenCaching  RDP通常会维护客户端中当前不可见的屏幕区域缓存，以加快在显示区域时的检索速度。将此参数设置为“ true”时，将禁用这些区域的缓存。
     *                                 这通常仅在处理RDP服务器实现中的已知错误时有用，并且在大多数情况下应保持启用状态。
     *                                 <p>
     * @param disableGlyphCaching      除了屏幕区域之外，RDP还维护了常用符号或字体的缓存，这些符号或字体统称为“字形”。
     *                                 与位图和屏幕外缓存一样，启用此功能后，RDP实现中的某些已知错误会导致性能问题，并且将此参数设置为“ true”将禁用RDP会话中的字形缓存。
     */
    public void performanceFlags(boolean enableWallpaper, boolean enableTheming, boolean enableFontSmoothing, boolean enableFullWindowDrag, boolean enableDesktopComposition,
                                 boolean enableMenuAnimations, boolean disableBitmapCaching, boolean disableOffscreenCaching, boolean disableGlyphCaching) {
        super.getGuacamoleConfiguration().setParameter("enable-wallpaper", String.valueOf(enableWallpaper));
        super.getGuacamoleConfiguration().setParameter("enable-theming", String.valueOf(enableTheming));
        super.getGuacamoleConfiguration().setParameter("enable-font-smoothing", String.valueOf(enableFontSmoothing));
        super.getGuacamoleConfiguration().setParameter("enable-full-window-drag", String.valueOf(enableFullWindowDrag));
        super.getGuacamoleConfiguration().setParameter("enable-desktop-composition", String.valueOf(enableDesktopComposition));
        super.getGuacamoleConfiguration().setParameter("enable-menu-animations", String.valueOf(enableMenuAnimations));
        super.getGuacamoleConfiguration().setParameter("disable-bitmap-caching", String.valueOf(disableBitmapCaching));
        super.getGuacamoleConfiguration().setParameter("disable-offscreen-caching", String.valueOf(disableOffscreenCaching));
        super.getGuacamoleConfiguration().setParameter("disable-glyph-caching", String.valueOf(disableGlyphCaching));
    }

    /**
     * 远程应用
     * <p>
     * Windows的最新版本提供了称为RemoteApp的功能，该功能允许通过RDP使用单个应用程序，而无需提供对完整桌面环境的访问。
     * 如果您的RDP服务器启用并配置了此功能，则可以将Guacamole连接配置为使用这些单独的应用程序。
     * <p>
     *
     * @param remoteApp     指定要在远程桌面上启动的RemoteApp。如果您的远程桌面服务器支持，则该应用程序和只有该应用程序对用户可见。
     *                      Windows对于远程应用程序的名称需要特殊的符号。远程应用程序的名称必须以两个竖线作为前缀。
     *                      例如，如果您在服务器上为其创建了一个远程应用程序，notepad.exe并为其 分配了名称“ notepad”，则可以将此参数设置为：“ \\ notepad”。
     *                      <p>
     * @param remoteAppDir  远程应用程序的工作目录（如果有）。如果不使用RemoteApp，则此参数无效。
     *                      <p>
     * @param remoteAppArgs 远程应用程序的命令行参数（如果有）。如果不使用RemoteApp，则此参数无效。
     */
    public void remoteApp(String remoteApp, String remoteAppDir, String remoteAppArgs) {
        super.getGuacamoleConfiguration().setParameter("remote-app", remoteApp);
        if (remoteAppDir != null) {
            super.getGuacamoleConfiguration().setParameter("remote-app-dir", remoteAppDir);
        }
        if (remoteAppArgs != null) {
            super.getGuacamoleConfiguration().setParameter("remote-app-args", remoteAppArgs);
        }
    }

    /**
     * 以逗号分隔的静态通道名称列表，以打开并将其公开为管道。如果您希望在远程桌面上运行的应用程序和JavaScript之间进行通信，这是最好的方法。鳄梨酱会打开一个带有静态通道名称的出站管道。如果JavaScript需要在另一个方向进行通讯，则应通过打开另一个具有相同名称的管道来进行响应。
     * 鳄梨酱允许打开任意数量的静态通道，但是RDP的协议限制将每个通道名称的大小限制为7个字符。
     */
    public void staticChannels(String str) {
        if (str == null || str.equals("") || str.length() > 7) throw new RuntimeException("大小限制为7个字符");
        super.getGuacamoleConfiguration().setParameter("static-channels", str);
    }

    /**
     * 预连接PDU（Hyper-V）
     * 送“预连接PDU”-一条消息，其中包含唯一标识目标的值，称为“ RDP源”。该机制由RDP协议的“会话选择扩展”定义，并由Microsoft的Hyper-V虚拟机管理程序实现。
     * <p>
     * 如果使用的是Hyper-V，则需要在preconnection-blob参数中指定目标虚拟机的ID 。可以使用PowerShell确定此值：
     * <p>
     * PS C:\> Get-VM VirtualMachineName | Select-Object Id
     * <p>
     * Id
     * --
     * ed272546-87bd-4db9-acba-e36e1a9ca20a
     * <p>
     * <p>
     * PS C:\>
     * 预连接PDU是有意通用的。虽然它的主要用途是在Hyper-V之后选择虚拟机的方法，但其他RDP服务器也可以使用它。由RDP服务器本身来确定是使用预连接ID，BLOB还是同时使用两者，以及它们的值是什么。
     * <p>
     * 如果确实打算使用Hyper-V，请注意其内置的RDP服务器在身份验证和端口号上使用略有不同的参数，并且Guacamole的默认设置将不起作用。在大多数情况下，连接到Hyper-V时需要执行以下操作：
     * <p>
     * 1.将“ servicePort” 设置为“ 2179”，因为这是Hyper-V使用的默认端口。标准RDP端口为3389，并且除非指定了其他值，否则鳄梨酱会使用端口3389。
     * <p>
     * 2.分别指定“ username”和“ password”，并将“ security” 设置为“ nla”或“ any”。Hyper-V需要连接客户端的网络级别身份验证。Guacamole的默认设置是使用标准的RDP加密，而无需网络级身份验证，而Hyper-V不支持。
     * <p>
     * 3.如有必要，将“ ignore-cert” 设置为“ true”。Hyper-V可以使用自签名证书。
     *
     * @param preconnectionId   RDP源的数字ID。这是一个非负整数值，指示应该使用几个逻辑RDP连接中的哪个。
     *                          此参数是可选的，并且仅在RDP服务器被记录为需要时才需要。如果使用Hyper-V，则应留空。
     *                          <p>
     * @param preconnectionBlob 标识RDP源的任意字符串-由同一RDP服务器托管的潜在多个逻辑RDP连接之一。
     *                          该参数是可选的，并且仅当RDP服务器被记录为需要此参数（例如Hyper-V）时才需要。
     *                          在所有情况下，该参数的含义对于RDP协议本身都是不透明的，并且由RDP服务器决定。
     *                          对于Hyper-V，这将是目标虚拟机的ID。
     */
    public void PreconnectionPDU(Long preconnectionId, String preconnectionBlob) {
        super.getGuacamoleConfiguration().setParameter("preconnection_id", String.valueOf(preconnectionId));
        super.getGuacamoleConfiguration().setParameter("preconnection_blob", preconnectionBlob);
    }

}
